package com.ronds.webtest.util;


import org.apache.log4j.Logger;
import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.testng.Assert;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import static com.ronds.webtest.util.DateUtil.getYearMonthDay;

/**
 * Created by zhanghui on 2017/7/3.
 */
public class WebElementUtil {

    private static final Logger logger = Logger.getLogger(WebElementUtil.class);
    private static WebDriver driver = WebDriverManager.getDriver();
    private static WebDriverWait wait = WebDriverManager.getWait();
    private static final int MAX_WAIT_TIME = 20;

    //等待操作
    public static void sleep(int seconds) {
        try {
            Thread.sleep(1000 * seconds);
        } catch (InterruptedException e) {
            logger.error(e);
        }
    }

    //获取当前url
    public static String getCurrentUrl() {
        return driver.getCurrentUrl();
    }



    //判断元素是否可定位到
    public static boolean isFound(String xpath) {
        if (driver.findElement(By.xpath(xpath)) != null) {
            return true;
        } else {
            return false;
        }
    }


    //判断元素是否存在
    public static boolean isExist(String xpath) {
        try {
            driver.findElement(By.xpath(xpath));
        } catch (Exception e) {
            sleep(2);
            try {
                driver.findElement(By.xpath(xpath));
            } catch (Exception e2) {
                return false;
            }
        }
        return true;
    }

    //页面刷新
    public static void refresh() {
        driver.navigate().refresh();
    }

    //页面回退
    public static void back() {
        driver.navigate().back();
    }

    //等待元素在html中不可见
    public static void waitElementDisappear(String xpath) {
        try {
            for (int i = 0; i < 5; i++) {
                if (driver.findElement(By.xpath(xpath)).isDisplayed()) {
                    sleep(1);
                } else return;
            }
            throw new ElementNotVisibleException(xpath + "该元素未消失");
        } catch (NoSuchElementException | StaleElementReferenceException e) {
            logger.error(e);
        }
    }

    //等待元素可见
    public static void waitElementAppear(String xpath) {
        try {
            for (int i = 0; i < MAX_WAIT_TIME; i++) {
                if (driver.findElement(By.xpath(xpath)).isDisplayed()) {
                    return;
                }
                sleep(1);
            }
        } catch (NoSuchElementException | StaleElementReferenceException e) {
            throw new ElementNotVisibleException(xpath + "元素未找到");
        }
    }

    //等待数据不为空
    public static void waitDataAppear(String Data) {
        try {
            for (int i = 0; i < MAX_WAIT_TIME; i++) {
                if (!StringUtils.isEmpty(Data)) {
                    return;
                }
                sleep(1);
            }
            throw new ElementNotVisibleException(Data + "数据为空");
        } catch (Exception e) {
            throw new ElementNotVisibleException(Data + "数据为空");
        }
    }


    //等待元素可见
    public static void isVisual(String xpath) {
        try {
            wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));

        } catch (Exception e) {
            throw new ElementNotVisibleException(xpath + "元素未找到");
        }

    }

    //等待元素不可见
    public static void isNotVisual(String xpath) {
        try {
            wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath(xpath)));
        }
        catch (Exception e)
        {
            takeErrorScreenshotAll();
            throw new ElementNotVisibleException("等待元素消失失败");
        }
    }

    //判断元素是否可见
    public static Boolean isDisplayed(String xpath) {
        return driver.findElement(By.xpath(xpath)).isDisplayed();
    }

    //等待元素出现并点击
    public static void waitAndClick(String xpath) {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
        try {
            driver.findElement(By.xpath(xpath)).click();
        } catch (Exception e) {
            JavascriptExecutor js = (JavascriptExecutor) driver;
            js.executeScript("arguments[0].click();", driver.findElement(By.xpath(xpath)));
        }
    }

    //根据文本进行点击
    public static void clickByText(String text) {
        WebElementUtil.waitAndClick("//*[contains(text(),'" + text + "')]");
    }

    //等待元素出现并输入
    public static void waitAndSendKeys(String xpath, String content) {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
        try {
            driver.findElement(By.xpath(xpath)).sendKeys(content);
        } catch (Exception e) {

        }
    }

    //等待元素出现并清空输入框
    public static void waitClearInput(String xpath) {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xpath)));
        driver.findElement(By.xpath(xpath)).clear();
    }

    //等待元素出现并清空输入框再输入
    public static void waitClearAndSendKeys(String xpath, String content) {
        waitClearInput(xpath);
        try {
            for (int i = 0; i < 10; i++) {
                if (StringUtils.isEmpty(waitAndGetText(xpath))) {
                    break;
                }
                sleep(1);
                waitClearInput(xpath);
            }
            if (!StringUtils.isEmpty(waitAndGetText(xpath))) {
                throw new ElementNotVisibleException("筛选项没有清空");
            }
        } catch (Exception e) {
            throw new ElementNotVisibleException("筛选项没有清空");
        }

        try {
            driver.findElement(By.xpath(xpath)).sendKeys(content);
        } catch (Exception e) {
            WebElementUtil.waitAndClick(xpath);
            Actions actions = new Actions(driver);
            actions.sendKeys(content).perform();
        }
    }

    //等待元素出现并输入再回车
    public static void waitAndSendKeysEnter(String xpath, String content) {
        waitAndSendKeys(xpath, content);
        driver.findElement(By.xpath(xpath)).sendKeys(Keys.ENTER);
    }


    //等待元素出现并清空输入框再输入再回车
    public static void waitClearAndSendKeysEnter(String xpath, String content) {
        waitClearAndSendKeys(xpath, content);
        driver.findElement(By.xpath(xpath)).sendKeys(Keys.ENTER);
    }

    public static void waitAndSendKeysEnter(String xpath) {
        isVisual(xpath);
        driver.findElement(By.xpath(xpath)).sendKeys(Keys.ENTER);
    }

    public static void waitAndSendKeysSpace(String xpath) {
        isVisual(xpath);
        driver.findElement(By.xpath(xpath)).sendKeys(Keys.SPACE);

    }

    public static void waitAndSenkKeysBack(String xpath) {
        isVisual(xpath);
        driver.findElement(By.xpath(xpath)).sendKeys(Keys.BACK_SPACE);
    }


    //等待元素出现并获取
    public static WebElement waitAndGetElement(String xpath) {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
        return driver.findElement(By.xpath(xpath));
    }

    //等待元素出现并获取系列符合要求的元素
    public static List<WebElement> waitAndGetElements(String xpath) {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
        return driver.findElements(By.xpath(xpath));
    }

    //等待元素出现并获取元素的内容
    public static String waitAndGetText(String xpath) {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
        return driver.findElement(By.xpath(xpath)).getText();
    }

    //等待元素出现并获取元素的属性内容
    public static String waitAndGetAttribute(String xpath, String attribute) {
        wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
        return driver.findElement(By.xpath(xpath)).getAttribute(attribute);
    }


    public static void findAndOpenInTableCol(String xpathTable, int colNo, String content) {
        WebElement table = waitAndGetElement(xpathTable);
        List<WebElement> rows = table.findElements(By.tagName("tr"));
        for (int i = 1; i < rows.size(); i++) {
            WebElement cell = rows.get(i).findElements(By.tagName("td")).get(colNo);
            if (cell.getText().contains(content)) {
                scrollIntoView(cell);
                cell.click();
                sleep(2);
                return;
            }
        }
    }

    public static void findInTableColAndSelect(String xpathTable, int count, int colNo, String content) {
        WebElement table = waitAndGetElement(xpathTable);
        List<WebElement> rows = table.findElements(By.tagName("tr"));
        int selected = 0;
        for (int i = 1; i < rows.size(); i++) {
            WebElement toggle = rows.get(i).findElements(By.tagName("td")).get(0).findElement(By.tagName("i"));
            if (content == null) {
                toggle.click();
                selected += 1;
            } else {
                WebElement cell = rows.get(i).findElements(By.tagName("td")).get(colNo);
                if (cell.getText().contains(content)) {
                    toggle.click();
                    selected += 1;
                }
            }
            if (selected >= count) {
                break;
            }
        }
    }

    public static void selectInTable(String xpathTable, int count) {
        findInTableColAndSelect(xpathTable, count, 0, null);
    }

    // 将web元素滚动到显示位置
    public static void scrollIntoView(WebElement element) {
        ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", element);
    }

    //切换Frame句柄到新框架
    public static void switchFrame(String xpath) throws Exception {
        try {
            driver.switchTo().frame(driver.findElement(By.xpath(xpath)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //切换Frame句柄到主框架
    public static void switchFrame() {
        driver.switchTo().defaultContent();
    }


    //校验元素不应该存在
    public static void validateElementNotExist(String xpath, String msg) {
        String method = new Exception().getStackTrace()[1].getMethodName();
        if (isExist(xpath)) {
            throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + msg + "不应该出现 ");
        } else {
            logger.info("当前调用方法:" + method + "||" + msg + "校验成功");
        }
    }


    //校验元素存在
    public static void validateElementExist(String xpath, String msg) {
        String method = new Exception().getStackTrace()[1].getMethodName();
        if (!isExist(xpath)) {
            takeErrorScreenshotAll();
            throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + msg + "无法找到");
        } else {
            logger.info("当前调用方法:" + method + "||" + msg + "校验成功");
        }
    }

    //校验元素存在并且文案正确-根据Text
    public static void validateElementExistAndText(String xpath, String msg, String errormsg) {
        String method = new Exception().getStackTrace()[1].getMethodName();
        if (!isExist(xpath)) {
            takeErrorScreenshotAll();
            throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + "||" + errormsg + "无法找到");
        } else {
            String validateMsg = waitAndGetText(xpath);
            for (int i = 0; i < 10; i++) {
                if (!StringUtils.isEmpty(validateMsg)) {
                    break;
                }
                sleep(1);
            }
            if (!validateMsg.equals(msg)) {
                takeErrorScreenshotAll();
                throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + "||" + errormsg + "文案不正确" + "||" + "实际文案："
                        + validateMsg + "||" + "预期文案：" + msg);
            } else {
                logger.info("当前调用方法:" + method + "||" + errormsg + "校验成功");
            }
        }
    }


    //校验元素存在并且文案正确-根据Attribute
    public static void validateElementExistAndAttribute(String xpath, String msg, String errormsg) {
        String method = new Exception().getStackTrace()[1].getMethodName();
        if (!isExist(xpath)) {
            takeErrorScreenshotAll();
            throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + "||" + errormsg + "无法找到");
        } else {
            try {
                String validateMsg = waitAndGetAttribute(xpath, "value");
                for (int i = 0; i < 10; i++) {
                    if (!StringUtils.isEmpty(validateMsg)) {
                        break;
                    }
                    sleep(1);
                }
                if (!validateMsg.equals(msg)) {
                    takeErrorScreenshotAll();
                    takeErrorScreenshot(xpath);
                    throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + "||" + errormsg + "文案不正确" + "||" + "实际文案：" + validateMsg +
                            "||" + "预期文案：" + msg);
                } else {
                    logger.info("当前调用方法:" + method + errormsg + "校验成功");
                }
            } catch (NullPointerException e) {
                throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + "||" + errormsg + "未找到元素");
            }
        }

    }

    //截图某个元素
    public static void takeErrorScreenshot(String xpath) {
        String currentDay = getYearMonthDay();
        String method = new Exception().getStackTrace()[1].getMethodName();
        WebElement webElement = waitAndGetElement(xpath);
        File srcFile = webElement.getScreenshotAs(OutputType.FILE);
        try {
            FileCopyUtils.copy(srcFile, new File(System.getProperty("user.dir") + "/src/main/resources/Error", currentDay + method + System.currentTimeMillis() + ".png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //截图整个图
    public static void takeErrorScreenshotAll() {
        String currentDay = getYearMonthDay();
        String method = new Exception().getStackTrace()[1].getMethodName();
        File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        try {
            FileCopyUtils.copy(srcFile, new File(System.getProperty("user.dir") + "/src/main/resources/File", currentDay + method + System.currentTimeMillis() + ".png"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //判断元素的颜色与预期是否一致
    public static void validateElementColor(String xpath, String rgba, String msg) {
        String method = new Exception().getStackTrace()[1].getMethodName();
        if (isExist(xpath)) {
            String expectedRgba = waitAndGetElement(xpath).getCssValue("color");
            if (expectedRgba.equals(rgba)) {
                logger.info("当前调用方法:" + method + "||" + msg + "颜色校验成功");
            } else {
                takeErrorScreenshotAll();
                throw new ElementNotVisibleException("当前调用方法:" + method + "||" + xpath + "||" + msg + "该元素颜色与预期不符");
            }

        } else {
            throw new ElementNotVisibleException("当前调用方法:" + method + "||" + "xpath:" + xpath + "||" + msg + "未找到元素");
        }
    }


    //切换到新窗口判断url，关闭并切换回来
    public static void checkNewPageURL(String oldHandle, String URL) {
        Set<String> handles = driver.getWindowHandles();
        Iterator iterator = handles.iterator();
        Boolean flag = false;
        while (iterator.hasNext()) {
            String h = (String) iterator.next();
            if (!h.equals(oldHandle)) {
                driver.switchTo().window(h);
                flag = true;
                break;
            }
        }
        if (!flag) {
            Assert.assertTrue(false, "没有打开新页面");
        }
        if (!WebElementUtil.getCurrentUrl().equals(URL)) {
            flag = false;
        }
        driver.close();
        handles = driver.getWindowHandles();
        iterator = handles.iterator();
        while (iterator.hasNext()) {
            String h = (String) iterator.next();
            if (h.equals(oldHandle)) {
                driver.switchTo().window(h);
                break;
            }
        }
        if (!flag) {
            Assert.assertTrue(false, "新页面URL与预期不符");
        }
    }

    //鼠标悬停
    public static void mouseOver(String xpath) {
        new Actions(driver).moveToElement(driver.findElement(By.xpath(xpath))).perform();
    }


    //是否可点击
    public static boolean isClickable(String xpath) {
        if (driver.findElement(By.xpath(xpath)).isEnabled()) {
            return true;
        }
        return false;

    }

    // 点击具体页码
    public static void clickPageNum(int pageNum, String xpathPageBtn) {
        if (isExist(xpathPageBtn)) {
            List<WebElement> pages = waitAndGetElements(xpathPageBtn);
            pages.get(pageNum + 2).click();
            sleep(1);
        }
    }

    //判断元素是否选中
    public static boolean isSelected(String xpath) {
        if (driver.findElement(By.xpath(xpath)).isSelected()) {
            return true;
        }
        return false;
    }

    //退出
    public static void quit() {
        driver.quit();
    }


    //浏览器最大
    public static void browserMax() {
        driver.manage().window().maximize();
    }




}
